package com.egghiro.framework.j2se.game.model.shape;

import java.io.Serializable;

public class SVector3D implements Serializable {

    private double x, y, z;

    public SVector3D(double value) {
        this(value, value, value);
    }

    public SVector3D(double x, double y, double z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public SVector3D(SVector3D vector3D) {
        this.x = vector3D.x;
        this.y = vector3D.y;
        this.z = vector3D.z;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }

    public void setZ(double z) {
        this.z = z;
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public double getZ() {
        return y;
    }

    public int x() {
        return (int) x;
    }

    public int y() {
        return (int) y;
    }

    public int z() {
        return (int) z;
    }

    public Object clone() {
        return new SVector3D(x, y, z);
    }

    public void move(SVector3D vector3D) {
        this.x += vector3D.x;
        this.y += vector3D.y;
        this.z += vector3D.z;
    }

    public void move(double x, double y, double z) {
        this.x += x;
        this.y += y;
        this.z += z;
    }

    public double[] getCoords() {
        return (new double[] { x, y, z });
    }

    public boolean equals(Object o) {
        if (o instanceof SVector3D) {
            SVector3D p = (SVector3D) o;
            return p.x == x && p.y == y && p.z == z;
        }
        return false;
    }

    public int hashCode() {
        return (int) (x + y + z);
    }

    public SVector3D add(SVector3D other) {
        double x = this.x + other.x;
        double y = this.y + other.y;
        double z = this.z + other.z;
        return new SVector3D(x, y, z);
    }

    public SVector3D subtract(SVector3D other) {
        double x = this.x - other.x;
        double y = this.y - other.y;
        double z = this.z - other.z;
        return new SVector3D(x, y, z);
    }

    public SVector3D multiply(double value) {
        return new SVector3D(value * x, value * y, value * z);
    }

    public SVector3D crossProduct(SVector3D other) {
        double x = this.y * other.z - other.y * this.z;
        double y = this.z * other.x - other.z * this.x;
        double z = this.x * other.y - other.x * this.y;
        return new SVector3D(x, y, z);
    }

    public double dotProduct(SVector3D other) {
        return other.x * x + other.y * y + other.z * z;
    }

    public SVector3D normalize() {
        double magnitude = Math.sqrt(dotProduct(this));
        return new SVector3D(x / magnitude, y / magnitude, z / magnitude);
    }

    public double level() {
        return Math.sqrt(dotProduct(this));
    }

    public SVector3D modulate(SVector3D other) {
        double x = this.x * other.x;
        double y = this.y * other.y;
        double z = this.z * other.z;
        return new SVector3D(x, y, z);
    }

    public String toString() {
        return (new StringBuffer("[Vector3D x:")).append(x).append(" y:").append(y).append(" z:").append(z).append("]")
                .toString();
    }

}
